/*
 * Copyright (C) 2008,2009,2010  Paulo Cesar Pereira de Andrade.
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Authors:
 *	Paulo Cesar Pereira de Andrade
 */

#ifndef _ecodes_h
#define _ecodes_h

#include "etypes.h"

#if defined(__GNUC__)
#  define GOTO_ADDRESS
#endif

enum ecode {
    ins_noop,		/* 00000000 */

    x00000001,		/* 00000001 */
    x00000010,		/* 00000010 */
    x00000011,		/* 00000011 */


    /*******************************************************************
     * load dst pointer
     *******************************************************************/

    /* accumulators */
    ins_ld_dr,		/* 00000100 */
    ins_ld_sr,		/* 00000101 */

    /* stack variable */
    ins_ld_bp_c,	/* 00000110 */
    ins_ld_bp_s,	/* 00000111 */
    ins_ld_bp_i,	/* 00001000 */

    /* heap variable */
    ins_ld_hp_c,	/* 00001001 */
    ins_ld_hp_s,	/* 00001010 */
    ins_ld_hp_i,	/* 00001011 */

    x00001100,		/* 00001100 */
    x00001101,		/* 00001101 */

    __ins_ld_d,		/* 00001110 */

    ins_ld_s,		/* 00001111 */

    /* struct field */
    ins_ld_d_c,		/* 00010000 */
    ins_ld_d_s,		/* 00010001 */
    ins_ld_d_i,		/* 00010010 */

    x00010011,		/* 00010011 */

    /* vector dereference */
    ins_ld_xd_c,	/* 00010100 */
    ins_ld_xd_s,	/* 00010101 */
    ins_ld_xd_i,	/* 00010110 */
    ins_ld_xd_dr,	/* 00010111 */
    ins_ld_xs_sr,	/* 00011000 */

    /* FIXME add vector dereference with bounds checking here */
    x00011001,		/* 00011001 */
    x00011010,		/* 00011010 */
    x00011011,		/* 00011011 */
    x00011100,		/* 00011100 */
    x00011101,		/* 00011101 */
    x00011110,		/* 00011110 */
    x00011111,		/* 00011111 */


    /*******************************************************************
     * load src pointer
     *******************************************************************/

    /* immediate constant */
    ins_lsc_z,		/* 00100000 */
    ins_lss_z,		/* 00100001 */
    ins_lsi_z,		/* 00100010 */
    ins_lsl_z,		/* 00100011 */

    /* accumulators */
    ins_ls_dr,		/* 00100100 */
    ins_ls_sr,		/* 00100101 */

    /* stack variable */
    ins_ls_bp_c,	/* 00100110 */
    ins_ls_bp_s,	/* 00100111 */
    ins_ls_bp_i,	/* 00101000 */

    /* heap variable */
    ins_ls_hp_c,	/* 00101001 */
    ins_ls_hp_s,	/* 00101010 */
    ins_ls_hp_i,	/* 00101011 */

    x00101100,		/* 00101100 */
    x00101101,		/* 00101101 */

    ins_ls_d,		/* 00101110 */

    __ins_ls_s,		/* 00101111 */

    /* struct field */
    ins_ls_s_c,		/* 00110000 */
    ins_ls_s_s,		/* 00110001 */
    ins_ls_s_i,		/* 00110010 */

    x00110011,		/* 00110011 */

    /* vector dereference */
    ins_ls_xs_c,	/* 00110100 */
    ins_ls_xs_s,	/* 00110101 */
    ins_ls_xs_i,	/* 00110110 */
    ins_ls_xs_dr,	/* 00110111 */
    ins_ls_xs_sr,	/* 00111000 */

    /* FIXME add vector dereference with bounds checking here */
    x00111001,		/* 00111001 */
    x00111010,		/* 00111010 */
    x00111011,		/* 00111011 */
    x00111100,		/* 00111100 */
    x00111101,		/* 00111101 */
    x00111110,		/* 00111110 */
    x00111111,		/* 00111111 */


    /*******************************************************************
     * integer operations
     *******************************************************************/

    ins_movc,		/* 01000000 */
    ins_movs,		/* 01000001 */
    ins_movi,		/* 01000010 */
    ins_movl,		/* 01000011 */
    ins_addc,		/* 01000100 */
    ins_adds,		/* 01000101 */
    ins_addi,		/* 01000110 */
    ins_addl,		/* 01000111 */
    ins_subc,		/* 01001000 */
    ins_subs,		/* 01001001 */
    ins_subi,		/* 01001010 */
    ins_subl,		/* 01001011 */
    ins_cmpc,		/* 01001100 */
    ins_cmps,		/* 01001101 */
    ins_cmpi,		/* 01001110 */
    ins_cmpl,		/* 01001111 */
    ins_mulc,		/* 01010000 */
    ins_muls,		/* 01010001 */
    ins_muli,		/* 01010010 */
    ins_mull,		/* 01010011 */
    ins_divc,		/* 01010100 */
    ins_divs,		/* 01010101 */
    ins_divi,		/* 01010110 */
    ins_divl,		/* 01010111 */
    ins_remc,		/* 01011000 */
    ins_rems,		/* 01011001 */
    ins_remi,		/* 01011010 */
    ins_reml,		/* 01011011 */
    ins_negc,		/* 01011100 */
    ins_negs,		/* 01011101 */
    ins_negi,		/* 01011110 */
    ins_negl,		/* 01011111 */
    ins_andc,		/* 01100000 */
    ins_ands,		/* 01100001 */
    ins_andi,		/* 01100010 */
    ins_andl,		/* 01100011 */
    ins_orc,		/* 01100100 */
    ins_ors,		/* 01100101 */
    ins_ori,		/* 01100110 */
    ins_orl,		/* 01100111 */
    ins_xorc,		/* 01101000 */
    ins_xors,		/* 01101001 */
    ins_xori,		/* 01101010 */
    ins_xorl,		/* 01101011 */
    ins_shlc,		/* 01101100 */
    ins_shls,		/* 01101101 */
    ins_shli,		/* 01101110 */
    ins_shll,		/* 01101111 */
    ins_shrc,		/* 01110000 */
    ins_shrs,		/* 01110001 */
    ins_shri,		/* 01110010 */
    ins_shrl,		/* 01110011 */
    ins_notc,		/* 01110100 */
    ins_nots,		/* 01110101 */
    ins_noti,		/* 01110110 */
    ins_notl,		/* 01110111 */
    ins_incc,		/* 01111000 */
    ins_incs,		/* 01111001 */
    ins_inci,		/* 01111010 */
    ins_incl,		/* 01111011 */
    ins_decc,		/* 01111100 */
    ins_decs,		/* 01111101 */
    ins_deci,		/* 01111110 */
    ins_decl,		/* 01111111 */


    /*******************************************************************
     * stack operations
     *******************************************************************/

    ins_pushc,		/* 10000000 */
    ins_pushs,		/* 10000001 */
    ins_pushi,		/* 10000010 */
    ins_pushl,		/* 10000011 */
    ins_push_d,		/* 10000100 */
    ins_push_s,		/* 10000101 */
    ins_push_bp,	/* ?? 10000110 */
    ins_push_sp,	/* ?? 10000111 */
    ins_push_ip,	/* ?? 10001000 */
    ins_push_fl,	/* ?? 10001001 */
    ins_popc,		/* 10001010 */
    ins_pops,		/* 10001011 */
    ins_popi,		/* 10001100 */
    ins_popl,		/* 10001101 */
    ins_pop_d,		/* 10001110 */
    ins_pop_s,		/* 10001111 */
    ins_pop_bp,		/* ?? 10010000 */
    ins_pop_sp,		/* ?? 10010001 */
    ins_pop_ip,		/* ?? 10010010 */
    ins_pop_fl,		/* ?? 10010011 */

    ins_pad,		/* ** 10010100 */
    ins_padz,		/* 10010101 */


     /* load dst accumulator with immediate */
    ins_ldrc,		/* 10010110 */
    ins_ldrs,		/* 10010111 */
    ins_ldri,		/* 10011000 */
    ins_ldrl,		/* 10011001 */

     /* load src accumulator with immediate */
    ins_lsrc,		/* 10011010 */
    ins_lsrs,		/* 10011011 */
    ins_lsri,		/* 10011100 */
    ins_lsrl,		/* 10011101 */


    x10011110,		/* 10011110 */

    ins_swap_d_s,	/* 10011111 */


    /*******************************************************************
     * jumps and function call/return
     *******************************************************************/

    ins_jmpc,		/* 10100000 */
    ins_jmps,		/* 10100001 */
    ins_jmpa,		/* 10100010 */
    x10100011,		/* 10100011 */
    ins_jne,		/* 10100100 */
    ins_jlt,		/* 10100101 */
    ins_jle,		/* 10100110 */
    ins_je,		/* 10100111 */
    ins_jge,		/* 10101000 */
    ins_jgt,		/* 10101001 */
    ins_jmp_d,		/* ?? 10101010 */
    ins_jmp_s,		/* ?? 10101011 */
    ins_enter,		/* 10101100 */
    ins_leave,		/* 10101101 */
    ins_calli,		/* 10101110 */
    x10101111,		/* 10101111 */
    x10110000,		/* 10110000 */
    ins_call_s,		/* ?? 10110001 */
    ins_ret,		/* ?? 10110010 */
    ins_reti,		/* 10110011 */

    x10110100,		/* 10110100 */


     /* generic memory block operations */

    ins_mcpy,		/* ?? 10110101 */
    ins_mmov,		/* ?? 10110110 */
    ins_mset,		/* ?? 10110111 */

    x10111000,		/* 10111000 */
    x10111001,		/* 10111001 */

    ins_new,		/* ?? 10111010 */
    ins_rsz,		/* ?? 10111011 */

    x10111100,		/* 10111100 */
    x10111101,		/* 10111101 */
    x10111110,		/* 10111110 */
    x10111111,		/* 10111111 */


    /*******************************************************************
     * type conversion
     *******************************************************************/

    ins_cvt_sc,		/* 11000000 */
    ins_cvt_ic,		/* 11000001 */
    ins_cvt_lc,		/* 11000010 */
    ins_cvt_is,		/* 11000011 */
    ins_cvt_ls,		/* 11000100 */
    ins_cvt_li,		/* 11000101 */
    ins_cvt_fl,		/* 11000110 */
    ins_cvt_dl,		/* 11000111 */
    ins_cvt_lf,		/* 11001000 */
    ins_cvt_ld,		/* 11001001 */
    ins_cvt_fd,		/* 11001010 */
    ins_cvt_df,		/* 11001011 */

    /* for big endian; but useful to keep track of types */
    ins_cvt_cs,		/* 11001100 */
    ins_cvt_ci,		/* 11001101 */
    ins_cvt_cl,		/* 11001110 */
    ins_cvt_si,		/* 11001111 */
    ins_cvt_sl,		/* 11010000 */
    ins_cvt_il,		/* 11010001 */

    x11010010,		/* 11010010 */
    x11010011,		/* 11010011 */


    /*******************************************************************
     * float operations
     *******************************************************************/

    ins_fclassf,	/* 11010100 */
    ins_fclassd,	/* 11010101 */
    ins_addf,		/* 11010110 */
    ins_addd,		/* 11010111 */
    ins_subf,		/* 11011000 */
    ins_subd,		/* 11011001 */
    ins_cmpf,		/* 11011010 */
    ins_cmpd,		/* 11011011 */
    ins_mulf,		/* 11011100 */
    ins_muld,		/* 11011101 */
    ins_divf,		/* 11011110 */
    ins_divd,		/* 11011111 */
    ins_remf,		/* 11100000 */
    ins_remd,		/* 11100001 */
    ins_negf,		/* 11100010 */
    ins_negd,		/* 11100011 */
    ins_acosf,		/* 11100100 */
    ins_acosd,		/* 11100101 */
    ins_atanf,		/* 11100110 */
    ins_atand,		/* 11100111 */
    ins_atan2f,		/* 11101000 */
    ins_atan2d,		/* 11101001 */
    ins_asinf,		/* 11101010 */
    ins_asind,		/* 11101011 */
    ins_cbrtf,		/* 11101100 */
    ins_cbrtd,		/* 11101101 */
    ins_ceilf,		/* 11101110 */
    ins_ceild,		/* 11101111 */
    ins_cosf,		/* 11110000 */
    ins_cosd,		/* 11110001 */
    ins_floorf,		/* 11110010 */
    ins_floord,		/* 11110011 */
    ins_logf,		/* 11110100 */
    ins_logd,		/* 11110101 */
    ins_log10f,		/* 11110110 */
    ins_log10d,		/* 11110111 */
    ins_powf,		/* 11111000 */
    ins_powd,		/* 11111001 */
    ins_sinf,		/* 11111010 */
    ins_sind,		/* 11111011 */
    ins_sqrtf,		/* 11111100 */
    ins_sqrtd,		/* 11111101 */
    ins_tanf,		/* 11111110 */
    ins_tand,		/* 11111111 */
};

struct eopcode {
    ecode_t	code;
    eobject_t	d;
    eobject_t	s;
};

#endif /* _ecodes_h */
